﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twitter;
using FriendsNearby.Services;
using FriendsNearby.Services.Entities;
using InSTEDD.Labs.Geo;

namespace FriendsNearbyBot
{
    public class FriendsQueryProcessor : IMessageProcessor
    {
        IUsersService userService;
        IPeopleNearbyService peopleService;
        IMessageBuilder messageBuilder;

        public FriendsQueryProcessor(IUsersService userService, IPeopleNearbyService peopleService)
            : this(userService, peopleService, new ListMessageBuilder())
        {
        }

        public FriendsQueryProcessor(IUsersService userService, IPeopleNearbyService peopleService, IMessageBuilder messageBuilder)
        {
            this.userService = userService;
            this.peopleService = peopleService;
            this.messageBuilder = messageBuilder;
        }

        public bool CanProcess(Message message)
        {
            string msg = message.Text;
            return (msg == "list all") || (msg.StartsWith("search") && msg.Length > "search".Length);
        }

        public RunNextProcessor Process(IBotClient client, Message message)
        {
            Func<PersonNearby, bool> filter = TryGetFilterForCommand(message.Text);

            if (filter != null)
            {
                UserRegistry user = userService.QueryUserRegistry(x=>x.TwitterScreenName == message.Sender.ScreenName);

                messageBuilder.Clear();
				if (user == null)
                {
                    // Warn the user via SMS that the mapping has not been established.
                    messageBuilder.AppendFragment(String.Format(Properties.Resources.TwitterNotMapped,
                        message.Sender.ScreenName));
                    client.SendMessages(message.Sender.ScreenName, messageBuilder.GetMessages(), message, this.GetType().Name);
                }
                else
                {
                    IEnumerable<PersonNearby> peopleNearby =
						peopleService.GetContacts(user.UserID, QueryContactsKind.Direct).Where(filter);

                    var peopleNearbyEmpty = true;
                    foreach (PersonNearby pn in peopleNearby)
                    {
                        peopleNearbyEmpty = false;
                        messageBuilder.AppendFragment(String.Format(Properties.Resources.PeopleNearbyResponse,
                                                            pn.DisplayName,
                                                            DistanceHelper.GetDistanceString(pn.Distance)));
                    }
                    if (peopleNearbyEmpty)
                    {
                        messageBuilder.AppendFragment(Properties.Resources.PeopleNearbyEmptyResponse);
                    }

                    client.SendMessages(message.Sender.ScreenName, messageBuilder.GetMessages(), message, this.GetType().Name);
                }

                BotProcessor.MessageProcessed(client, message);

                return RunNextProcessor.No;
            }
            else
            {
                return RunNextProcessor.Yes;
            }
        }

        /// <summary>
        /// Return null if command don't match
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        private Func<PersonNearby, bool> TryGetFilterForCommand(string msg)
        {
            // TODO: try different the case that the comman isn´t larger than seach.
            if (msg.Equals("list all"))
            {
                return x => true;
            }
            else if (msg.StartsWith("search") && msg.Length > "search".Length)
            {
                string criteria = msg.Substring("search".Length + 1);
                return x => x.DisplayName.ToLowerInvariant().Contains(criteria.ToLowerInvariant());
            }
            else
            {
                return null;
            }
        }
    }
}
